{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# How to attach callbacks to a module\n",
    "\n",
    ":::info Prerequisites\n",
    "\n",
    "This guide assumes familiarity with the following concepts:\n",
    "\n",
    "- [Callbacks](/docs/concepts/#callbacks)\n",
    "- [Chaining runnables](/docs/how_to/sequence)\n",
    "- [Attach runtime arguments to a Runnable](/docs/how_to/binding)\n",
    "\n",
    ":::\n",
    "\n",
    "If you are composing a chain of runnables and want to reuse callbacks across multiple executions, you can attach callbacks with the [`.withConfig()`](https://api.js.langchain.com/classes/langchain_core_runnables.Runnable.html#withConfig) method. This saves you the need to pass callbacks in each time you invoke the chain.\n",
    "\n",
    "Here's an example using LangChain's built-in [`ConsoleCallbackHandler`](https://api.js.langchain.com/classes/langchain_core_tracers_console.ConsoleCallbackHandler.html):"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\u001b[32m[chain/start]\u001b[39m [\u001b[90m\u001b[1m1:chain:RunnableSequence\u001b[22m\u001b[39m] Entering Chain run with input: {\n",
      "  \"number\": \"2\"\n",
      "}\n",
      "\u001b[32m[chain/start]\u001b[39m [\u001b[90m1:chain:RunnableSequence > \u001b[1m2:prompt:ChatPromptTemplate\u001b[22m\u001b[39m] Entering Chain run with input: {\n",
      "  \"number\": \"2\"\n",
      "}\n",
      "\u001b[36m[chain/end]\u001b[39m [\u001b[90m1:chain:RunnableSequence > \u001b[1m2:prompt:ChatPromptTemplate\u001b[22m\u001b[39m] [1ms] Exiting Chain run with output: {\n",
      "  \"lc\": 1,\n",
      "  \"type\": \"constructor\",\n",
      "  \"id\": [\n",
      "    \"langchain_core\",\n",
      "    \"prompt_values\",\n",
      "    \"ChatPromptValue\"\n",
      "  ],\n",
      "  \"kwargs\": {\n",
      "    \"messages\": [\n",
      "      {\n",
      "        \"lc\": 1,\n",
      "        \"type\": \"constructor\",\n",
      "        \"id\": [\n",
      "          \"langchain_core\",\n",
      "          \"messages\",\n",
      "          \"HumanMessage\"\n",
      "        ],\n",
      "        \"kwargs\": {\n",
      "          \"content\": \"What is 1 + 2?\",\n",
      "          \"additional_kwargs\": {},\n",
      "          \"response_metadata\": {}\n",
      "        }\n",
      "      }\n",
      "    ]\n",
      "  }\n",
      "}\n",
      "\u001b[32m[llm/start]\u001b[39m [\u001b[90m1:chain:RunnableSequence > \u001b[1m3:llm:ChatAnthropic\u001b[22m\u001b[39m] Entering LLM run with input: {\n",
      "  \"messages\": [\n",
      "    [\n",
      "      {\n",
      "        \"lc\": 1,\n",
      "        \"type\": \"constructor\",\n",
      "        \"id\": [\n",
      "          \"langchain_core\",\n",
      "          \"messages\",\n",
      "          \"HumanMessage\"\n",
      "        ],\n",
      "        \"kwargs\": {\n",
      "          \"content\": \"What is 1 + 2?\",\n",
      "          \"additional_kwargs\": {},\n",
      "          \"response_metadata\": {}\n",
      "        }\n",
      "      }\n",
      "    ]\n",
      "  ]\n",
      "}\n",
      "\u001b[36m[llm/end]\u001b[39m [\u001b[90m1:chain:RunnableSequence > \u001b[1m3:llm:ChatAnthropic\u001b[22m\u001b[39m] [797ms] Exiting LLM run with output: {\n",
      "  \"generations\": [\n",
      "    [\n",
      "      {\n",
      "        \"text\": \"1 + 2 = 3\",\n",
      "        \"message\": {\n",
      "          \"lc\": 1,\n",
      "          \"type\": \"constructor\",\n",
      "          \"id\": [\n",
      "            \"langchain_core\",\n",
      "            \"messages\",\n",
      "            \"AIMessage\"\n",
      "          ],\n",
      "          \"kwargs\": {\n",
      "            \"content\": \"1 + 2 = 3\",\n",
      "            \"tool_calls\": [],\n",
      "            \"invalid_tool_calls\": [],\n",
      "            \"additional_kwargs\": {\n",
      "              \"id\": \"msg_01WvZAqTg2hZzC4AKyeUaADs\",\n",
      "              \"type\": \"message\",\n",
      "              \"role\": \"assistant\",\n",
      "              \"model\": \"claude-3-sonnet-20240229\",\n",
      "              \"stop_sequence\": null,\n",
      "              \"usage\": {\n",
      "                \"input_tokens\": 16,\n",
      "                \"output_tokens\": 13\n",
      "              },\n",
      "              \"stop_reason\": \"end_turn\"\n",
      "            },\n",
      "            \"response_metadata\": {\n",
      "              \"id\": \"msg_01WvZAqTg2hZzC4AKyeUaADs\",\n",
      "              \"model\": \"claude-3-sonnet-20240229\",\n",
      "              \"stop_sequence\": null,\n",
      "              \"usage\": {\n",
      "                \"input_tokens\": 16,\n",
      "                \"output_tokens\": 13\n",
      "              },\n",
      "              \"stop_reason\": \"end_turn\"\n",
      "            }\n",
      "          }\n",
      "        }\n",
      "      }\n",
      "    ]\n",
      "  ],\n",
      "  \"llmOutput\": {\n",
      "    \"id\": \"msg_01WvZAqTg2hZzC4AKyeUaADs\",\n",
      "    \"model\": \"claude-3-sonnet-20240229\",\n",
      "    \"stop_sequence\": null,\n",
      "    \"usage\": {\n",
      "      \"input_tokens\": 16,\n",
      "      \"output_tokens\": 13\n",
      "    },\n",
      "    \"stop_reason\": \"end_turn\"\n",
      "  }\n",
      "}\n",
      "\u001b[36m[chain/end]\u001b[39m [\u001b[90m\u001b[1m1:chain:RunnableSequence\u001b[22m\u001b[39m] [806ms] Exiting Chain run with output: {\n",
      "  \"lc\": 1,\n",
      "  \"type\": \"constructor\",\n",
      "  \"id\": [\n",
      "    \"langchain_core\",\n",
      "    \"messages\",\n",
      "    \"AIMessage\"\n",
      "  ],\n",
      "  \"kwargs\": {\n",
      "    \"content\": \"1 + 2 = 3\",\n",
      "    \"tool_calls\": [],\n",
      "    \"invalid_tool_calls\": [],\n",
      "    \"additional_kwargs\": {\n",
      "      \"id\": \"msg_01WvZAqTg2hZzC4AKyeUaADs\",\n",
      "      \"type\": \"message\",\n",
      "      \"role\": \"assistant\",\n",
      "      \"model\": \"claude-3-sonnet-20240229\",\n",
      "      \"stop_sequence\": null,\n",
      "      \"usage\": {\n",
      "        \"input_tokens\": 16,\n",
      "        \"output_tokens\": 13\n",
      "      },\n",
      "      \"stop_reason\": \"end_turn\"\n",
      "    },\n",
      "    \"response_metadata\": {\n",
      "      \"id\": \"msg_01WvZAqTg2hZzC4AKyeUaADs\",\n",
      "      \"model\": \"claude-3-sonnet-20240229\",\n",
      "      \"stop_sequence\": null,\n",
      "      \"usage\": {\n",
      "        \"input_tokens\": 16,\n",
      "        \"output_tokens\": 13\n",
      "      },\n",
      "      \"stop_reason\": \"end_turn\"\n",
      "    }\n",
      "  }\n",
      "}\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "AIMessage {\n",
       "  lc_serializable: \u001b[33mtrue\u001b[39m,\n",
       "  lc_kwargs: {\n",
       "    content: \u001b[32m\"1 + 2 = 3\"\u001b[39m,\n",
       "    tool_calls: [],\n",
       "    invalid_tool_calls: [],\n",
       "    additional_kwargs: {\n",
       "      id: \u001b[32m\"msg_01WvZAqTg2hZzC4AKyeUaADs\"\u001b[39m,\n",
       "      type: \u001b[32m\"message\"\u001b[39m,\n",
       "      role: \u001b[32m\"assistant\"\u001b[39m,\n",
       "      model: \u001b[32m\"claude-3-sonnet-20240229\"\u001b[39m,\n",
       "      stop_sequence: \u001b[1mnull\u001b[22m,\n",
       "      usage: { input_tokens: \u001b[33m16\u001b[39m, output_tokens: \u001b[33m13\u001b[39m },\n",
       "      stop_reason: \u001b[32m\"end_turn\"\u001b[39m\n",
       "    },\n",
       "    response_metadata: {}\n",
       "  },\n",
       "  lc_namespace: [ \u001b[32m\"langchain_core\"\u001b[39m, \u001b[32m\"messages\"\u001b[39m ],\n",
       "  content: \u001b[32m\"1 + 2 = 3\"\u001b[39m,\n",
       "  name: \u001b[90mundefined\u001b[39m,\n",
       "  additional_kwargs: {\n",
       "    id: \u001b[32m\"msg_01WvZAqTg2hZzC4AKyeUaADs\"\u001b[39m,\n",
       "    type: \u001b[32m\"message\"\u001b[39m,\n",
       "    role: \u001b[32m\"assistant\"\u001b[39m,\n",
       "    model: \u001b[32m\"claude-3-sonnet-20240229\"\u001b[39m,\n",
       "    stop_sequence: \u001b[1mnull\u001b[22m,\n",
       "    usage: { input_tokens: \u001b[33m16\u001b[39m, output_tokens: \u001b[33m13\u001b[39m },\n",
       "    stop_reason: \u001b[32m\"end_turn\"\u001b[39m\n",
       "  },\n",
       "  response_metadata: {\n",
       "    id: \u001b[32m\"msg_01WvZAqTg2hZzC4AKyeUaADs\"\u001b[39m,\n",
       "    model: \u001b[32m\"claude-3-sonnet-20240229\"\u001b[39m,\n",
       "    stop_sequence: \u001b[1mnull\u001b[22m,\n",
       "    usage: { input_tokens: \u001b[33m16\u001b[39m, output_tokens: \u001b[33m13\u001b[39m },\n",
       "    stop_reason: \u001b[32m\"end_turn\"\u001b[39m\n",
       "  },\n",
       "  tool_calls: [],\n",
       "  invalid_tool_calls: []\n",
       "}"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import { ConsoleCallbackHandler } from \"@langchain/core/tracers/console\";\n",
    "import { ChatPromptTemplate } from \"@langchain/core/prompts\";\n",
    "import { ChatAnthropic } from \"@langchain/anthropic\";\n",
    "\n",
    "const handler = new ConsoleCallbackHandler();\n",
    "\n",
    "const prompt = ChatPromptTemplate.fromTemplate(`What is 1 + {number}?`);\n",
    "const model = new ChatAnthropic({\n",
    "  model: \"claude-3-sonnet-20240229\",\n",
    "});\n",
    "\n",
    "const chainWithCallbacks = prompt.pipe(model).withConfig({\n",
    "  callbacks: [handler],\n",
    "});\n",
    "\n",
    "await chainWithCallbacks.invoke({ number: \"2\" });"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The bound callbacks will run for all nested module runs.\n",
    "\n",
    "## Next steps\n",
    "\n",
    "You've now learned how to bind callbacks to a chain.\n",
    "\n",
    "Next, check out the other how-to guides in this section, such as how to create your own [custom callback handlers](/docs/how_to/custom_callbacks)."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Deno",
   "language": "typescript",
   "name": "deno"
  },
  "language_info": {
   "file_extension": ".ts",
   "mimetype": "text/x.typescript",
   "name": "typescript",
   "nb_converter": "script",
   "pygments_lexer": "typescript",
   "version": "5.3.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
